<!--
 * @Description: 百度地图弹框
 * @Author: Zhanghan
 * @Date: 2024-12-07 16:25:41
 * @LastEditTime: 2024-12-09 16:55:46
 * @LastEditors: Zhanghan
-->
<template>
  <div class="w-full h-full">
    <ProModal
      v-model:visible="visible"
      width="1200"
      @cancel="destroyMap"
      title="地图选择"
      @ok="handleOk"
      :use-type="2"
    >
      <ElInput
        placeholder="请输入地址"
        class="mb-2"
        style="width: 40%"
        v-model="searchValue"
        clearable
        :readonly="loading"
      >
        <template #append>
          <ElButton type="primary" @click="handleSearch">搜索</ElButton>
        </template>
      </ElInput>
      <div id="container" class="positionbox" v-loading="loading"></div>
    </ProModal>
    <ElButton type="primary" @click="handleClick">点击弹出地图</ElButton>
  </div>
</template>

<script lang="ts" setup>
import { ref, unref, watch } from "vue";
import { ProModal } from "@/components/ProComponents/index";
import { useMessage } from "@/hooks/useMessage";
import { ElButton, ElInput } from "element-plus";
import positionIcon from "@/assets/images/position.png";
import { LoadBaiduMapScript } from "./map";

const searchValue = ref(""); //搜索框

const emits = defineEmits(["selectAddress"]);
const visible = ref(false);
const loading = ref(false);
const address: any = ref("河南省郑州市二七区建设东路48号");
const lon: any = ref(113.65); //代表经度 (longitude)
const lat: any = ref(34.76); //代表纬度 (latitude)
const map: any = ref({});
const point: any = ref({});
const marker: any = ref({});
const current: any = ref({});
const message = useMessage();

const handleClick = () => {
  visible.value = true;
};

watch(visible, async (newVal) => {
  if (newVal) {
    await LoadBaiduMapScript();
    //必须在实例化之后才能获取到地图实例
    await initMap({});
    //定位
    await browserPosition();
  }
});

// 初始百度地图
const initMap = (record: any) => {
  address.value = record.address ? record.address : "郑州市";
  // 1.创建地图实例
  map.value = new BMap.Map("container");
  lon.value = record?.coordinates?.lon ?? lon.value ?? 113.65;
  lat.value = record?.coordinates?.lat ?? lat.value ?? 34.76;
  // 2.设置中心点
  point.value = new BMap.Point(113.65, 34.76);
  console.log("🚀 ~ initMap ~ point.value:", point.value, unref(map));
  // // // 3.设置级别
  unref(map).centerAndZoom(point.value, 15);
  // // 4.开启鼠标滚轮缩放功能。仅对PC上有效
  unref(map).enableScrollWheelZoom();
  const myIcon = new BMap.Icon(positionIcon, new BMap.Size(23, 25));
  marker.value = new BMap.Marker(point.value, myIcon);
  unref(map).addOverlay(marker.value); //添加一个标注
  // 打开信息窗口
  upInfoWindow();
  // 点击地图事件
  unref(map).addEventListener("click", function (e: any) {
    lon.value = e.point.lng;
    lat.value = e.point.lat;
    point.value = new BMap.Point(lon.value, lat.value);
    unref(map).centerAndZoom(point.value, 15);
    upInfoWindow();
    const gc = new BMap.Geocoder();
    gc.getLocation(point.value, (rs: any) => {
      if (rs && rs.address) {
        address.value = rs.address;
      }
    });
  });
};

// 打开信息窗口
const upInfoWindow = () => {
  const opts = {
    width: 250, // 信息窗口宽度
    height: 120, // 信息窗口高度
    title: "经纬度", // 信息窗口标题
  };
  console.log(unref(address));
  const word = `<div>地址：${unref(address)}</div>
                  <div>经度：${unref(lon)}</div>
                  <div>纬度：${unref(lat)}</div>`;
  const infoWindow = new BMap.InfoWindow(word, opts); // 创建信息窗口对象
  unref(map).openInfoWindow(infoWindow, point.value); // 打开信息窗口
  // 使信息窗口多次打开
  unref(marker).addEventListener("click", function () {
    unref(map).openInfoWindow(infoWindow, point.value);
  });
};

// 对搜索框中的文字进行逆解析
function geocoderLocation() {
  point.value = new BMap.Point(lon.value, lat.value);
  unref(map).centerAndZoom(unref(point), 15);
  unref(map).addOverlay(new BMap.Marker(unref(point)));
  const gc = new BMap.Geocoder();
  gc.getLocation(unref(point), (rs: any) => {
    console.log(rs);
    if (rs && rs.address) {
      address.value = rs.address;
      upInfoWindow();
    }
  });
}

// 搜索框改变事件
const handleSearch = () => {
  if (searchValue) {
    const value = searchValue.value.trim();
    //创建地址解析器实例
    const myGeo = new BMap.Geocoder();
    // 将地址解析结果显示在地图上，并调整地图视野
    myGeo.getPoint(
      value,
      async (point: any) => {
        if (point) {
          lon.value = point.lng;
          lat.value = point.lat;
          await geocoderLocation();
        } else {
          message({ type: "warning", message: "您选择的地址没有解析到结果！" });
        }
      },
      value
    );
  } else {
    message({ type: "warning", message: "搜索框不能为空" });
  }
};

// 浏览器定位
function browserPosition() {
  loading.value = true;
  const geolocation = new BMap.Geolocation();
  geolocation.getCurrentPosition((r: any) => {
    if (r) {
      (lon.value = r.point.lng), (lat.value = r.point.lat), geocoderLocation();
    } else {
      message({ type: "error", message: "定位失败，请手动输入经纬度" });
    }
    loading.value = false;
  });
}

//销毁地图实例
const destroyMap = () => {
  if (map.value) {
    // 清除地图上的所有标注、图层等
    map.value.clearOverlays();
    // 将 map 设为 null
    map.value = null;
    console.log("地图实例已销毁");
  }
};

//确认回调
const handleOk = () => {
  destroyMap();
  emits("selectAddress", {
    address: address.value,
    lon: lon.value,
    lat: lat.value,
  });
};
</script>

<style scoped lang="less">
.positionbox {
  width: 77vw;
  height: 64vh;
  margin-top: 20px;
}
</style>
